package org.myframework.commons.ftp.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.myframework.commons.ftp.CommonFtp;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class SFTPClient implements CommonFtp{
	/**
	 * Logger for this class
	 */

	private static final Logger logger = Logger.getLogger(SFTPClient.class);

	private ChannelSftp sftp;
	private Session session;

	public SFTPClient() {
		sftp = null;
	}

	public boolean connect(String host, String username, String password, int port) throws JSchException {
		try {
            if(sftp != null){
            	logger.debug("sftp is not null");
            }
            JSch jsch = new JSch();
            jsch.getSession(username, host, port);
            Session sshSession = jsch.getSession(username, host, port);
            logger.debug("Session created.");
            sshSession.setPassword(password);
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            logger.debug("Session connected.");
            logger.debug("Opening Channel.");
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            logger.debug("Connected to " + host + ".");
            return true ;
        } catch (Exception e) {
            e.printStackTrace();
            return false ;
        }
	}

	public void disconnect() {
		if (sftp != null) {
			sftp.exit();
		}
		if (session != null) {
			session.disconnect();
		}
		sftp = null;
	}

	public List<String> listFileInDir(String remoteDir) throws Exception {
		try {
			List<LsEntry> rs = sftp.ls(remoteDir);
			List<String> result = new ArrayList<String>();
			for (int i = 0; i < rs.size(); i++) {
				if (!isARemoteDirectory(rs.get(i).getFilename())) {
					result.add(rs.get(i).getFilename());
				}
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(remoteDir);
			throw new Exception(e);
		}
	}

	public List<String> listSubDirInDir(String remoteDir) throws Exception {
		List<LsEntry> rs = sftp.ls(remoteDir);
		List<String> result = new ArrayList<String>();
		for (int i = 0; i < rs.size(); i++) {
			if (isARemoteDirectory(rs.get(i).getFilename())) {
				result.add(rs.get(i).getFilename());
			}
		}
		return result;
	}

	protected boolean createDirectory(String dirName) {
		try {
			sftp.mkdir(dirName);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	protected boolean downloadFileAfterCheck(String remotePath, String localPath) throws IOException {
		FileOutputStream outputSrr = null;
		try {
			File file = new File(localPath);
			if (!file.exists()) {
				outputSrr = new FileOutputStream(localPath);
				sftp.get(remotePath, outputSrr);
			}
		} catch (SftpException e) {
			try {
				logger.error(remotePath + " not found in " + sftp.pwd());
			} catch (SftpException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
			return false;
		} finally {
			if (outputSrr != null) {
				outputSrr.close();
			}
		}
		return true;
	}

	protected boolean downloadFile(String remotePath, String localPath) throws IOException {
		FileOutputStream outputSrr = new FileOutputStream(localPath);
		try {
			sftp.get(remotePath, outputSrr);
		} catch (SftpException e) {
			try {
				logger.error(remotePath + " not found in " + sftp.pwd());
			} catch (SftpException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
			return false;
		} finally {
			if (outputSrr != null) {
				outputSrr.close();
			}
		}
		return true;
	}

	public boolean uploadFile(String localPath, String remotePath) throws IOException {
		FileInputStream inputSrr = new FileInputStream(localPath);
		try {
			sftp.put(inputSrr, remotePath);
		} catch (SftpException e) {
			e.printStackTrace();
			return false;
		} finally {
			if (inputSrr != null) {
				inputSrr.close();
			}
		}
		return true;
	}

	public boolean uploadFile(InputStream inputSrr , String remotePath) throws IOException {
		try {
			sftp.put(inputSrr, remotePath);
		} catch (SftpException e) {
			e.printStackTrace();
			return false;
		} finally {
			if (inputSrr != null) {
				inputSrr.close();
			}
		}
		return true;
	}

	public boolean changeDir(String remotePath) throws Exception {
		try {
			sftp.cd(remotePath);
		} catch (SftpException e) {
			return false;
		}
		return true;
	}

	public boolean isARemoteDirectory(String path) {
		try {
			return sftp.stat(path).isDir();
		} catch (SftpException e) {
			//e.printStackTrace();
		}
		return false;
	}

	public String getWorkingDirectory() {
		try {
			return sftp.pwd();
		} catch (SftpException e) {
			e.printStackTrace();
		}
		return null;
	}

}
